package br.com.brasilprojetos;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class SpaceHeroGame extends Activity {

	/** CONSTANTS */
	private static final int MAX_FPS = 25;
	
	private static final int MAX_FRAME_SKIP = 5;
	
	private static final int FRAME_TIME = 1000 / SpaceHeroGame.MAX_FPS;
	
	private static final long NANOSECONDS_PER_MILISECOND = 1000000;
	
	/***/
	private long mNextFrameTick;
	
	/***/
	private boolean mPaused;
	
	/***/
	private boolean mRunning;
	
	/** The OpenGL View */
	private GLSurfaceView glSurface;
	
	/***/
	private final UpdateThread mUpdateThread;
	
	public SpaceHeroGame()
	{
		super();

		this.mPaused = false;
		this.mRunning = false;
		
		this.mNextFrameTick = 0;
		this.mUpdateThread = new UpdateThread(this);
	}

	private boolean isRunning() {
		return this.mRunning;
	}
	
	private long getSytemTick(){
		return System.nanoTime() / SpaceHeroGame.NANOSECONDS_PER_MILISECOND;
	}

	/**
	 * Initiate the OpenGL View and set our own Renderer (@see Lesson02.java)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// Create an Instance with this Activity
		glSurface = new GLSurfaceView(this);
		// Set our own Renderer
		SpaceHeroRenderer te = new SpaceHeroRenderer();
		glSurface.setRenderer(te);
		glSurface.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
		// glSurface.setOnTouchListener(te);
		// Set the GLSurface as View to this Activity
		setContentView(glSurface);
		
		this.Start();
	}

	/**
	 * Remember to resume the glSurface
	 */
	@Override
	protected void onResume() {
		super.onResume();
		glSurface.onResume();
		this.Pause(false);
	}
	
	/**
	 * Also pause the glSurface
	 */
	@Override
	protected void onPause() {
		super.onPause();
		glSurface.onPause();
		this.Pause(true);
	}
	
	@Override
	protected void onDestroy(){
		super.onDestroy();
		this.Stop();
	};
	
	/**
	 * Start the game and UpdateThread
	 */
	public void Start() {
		this.mPaused = false;
		this.mRunning = true;
		
		this.mNextFrameTick = this.getSytemTick();
		this.mUpdateThread.start();
	}

	/**
	 * Stop the game and UpdateThread
	 */
	public void Stop() {
		this.mPaused = false;
		this.mRunning = false;
	}

	/**
	 * Pause the game
	 */
	public void Pause(boolean pPause) {
		this.mPaused = pPause;
	}
	
	/**
	 * Update game and time and draw the game.
	 */
	public /*synchronized*/ void onTickUpdate() throws InterruptedException
	{
		long updateStartTick = this.getSytemTick();
		this.UpdateGame();
		this.DrawGame();
		
		long sleepTime = SpaceHeroGame.FRAME_TIME - (this.getSytemTick() - updateStartTick);
		if(sleepTime > 0)
		{
			Thread.sleep(sleepTime);
		}
	}
	
	/**
	 * Update the game.
	 */
	private void UpdateGame()
	{
		if(this.mPaused)
		{
			this.mNextFrameTick += SpaceHeroGame.FRAME_TIME;;
		}
		else
		{
			int loopCount = 0;
			while(	this.getSytemTick() > this.mNextFrameTick &&
					loopCount < SpaceHeroGame.MAX_FRAME_SKIP)
			{
				this.UpdateScene();
				this.mNextFrameTick += SpaceHeroGame.FRAME_TIME;
				loopCount++;
			}
		}
	}
	
	/**
	 * Update the game scene
	 */
	private void UpdateScene(){
		
	}
	
	/**
	 * Draw the game.
	 */
	private void DrawGame(){
		float interpolation = (float)(this.getSytemTick() + SpaceHeroGame.FRAME_TIME - this.mNextFrameTick) / (float)SpaceHeroGame.FRAME_TIME;
		this.DrawScene(interpolation);
		glSurface.requestRender();
	}

	
	/**
	 * Draw the game scene.
	 */
	private void DrawScene(float pInterpolation){
		
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

	/**
	 * Thread the update de game
	 */
	private class UpdateThread extends Thread {
		
		private SpaceHeroGame mGame;
		
		public UpdateThread(SpaceHeroGame pGame) {
			super("UpdateThread");
			
			this.mGame = pGame;
		}

		@Override
		public void run() {
			android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DEFAULT);
			try {
				while(this.mGame.isRunning()) {
					this.mGame.onTickUpdate();
				}
			} catch (final InterruptedException e) {
				this.interrupt();
			}
		}
	}
}
